package com.fuyun.rpc.common.utils;

import com.github.javafaker.Faker;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.function.Supplier;

/**
 * @author: zrq1351
 * @date: 2025/2/14
 */
@Slf4j
public class MockDataUtil {
	private static final Faker FAKER = new Faker();
	private static final Map<Class<?>, Supplier<?>> GENERATORS = new HashMap<>();

	// 注册默认生成器
	static {
		GENERATORS.put(String.class, () -> FAKER.name().name());
		GENERATORS.put(Integer.class, () -> FAKER.number().randomDigit());
		GENERATORS.put(Double.class, () -> FAKER.number().randomDouble(2, 1, 100));
		GENERATORS.put(Long.class, () -> FAKER.number().randomNumber());
		GENERATORS.put(Boolean.class, () -> FAKER.bool().bool());
		GENERATORS.put(BigDecimal.class, () -> new BigDecimal(FAKER.number().randomDigit()));
		GENERATORS.put(UUID.class, UUID::randomUUID);
		GENERATORS.put(Date.class, () -> FAKER.date().birthday());
		GENERATORS.put(LocalDate.class, LocalDate::now);
		GENERATORS.put(LocalDateTime.class, LocalDateTime::now);
	}

	/**
	 * 生成模拟数据
	 *
	 * @param clazz
	 * @param <T>
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> T generate(Class<T> clazz) {
		try {
			// 处理数组
			if (clazz.isArray()) {
				return (T)generateArray(clazz.getComponentType());
			}
			// 处理注册过的类型
			if (GENERATORS.containsKey(clazz)) {
				return ((Supplier<T>)GENERATORS.get(clazz)).get();
			}
		} catch (Exception e) {
			return null;
		}
		// 处理自定义对象
		return generatePojo(clazz);
	}

	/**
	 * 生成自定义对象
	 *
	 * @param clazz
	 * @param <T>
	 * @return
	 */
	private static <T> T generatePojo(Class<T> clazz) {
		try {
			T instance = clazz.getDeclaredConstructor().newInstance();
			Object value;
			for (Field field : clazz.getDeclaredFields()) {
				field.setAccessible(true);
				Class<?> fieldType = field.getType();
				value = generate(fieldType);
				field.set(instance, value);
			}
			return instance;
		} catch (Exception e) {
			return null;
		}
	}

	/**
	 * 生成数组
	 *
	 * @param componentType
	 * @return
	 */
	private static Object generateArray(Class<?> componentType) {
		Object array = Array.newInstance(componentType, 3);
		for (int i = 0; i < 3; i++) {
			Array.set(array, i, generate(componentType));
		}
		return array;
	}

}